using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Text;
using System.Windows.Forms;
using DigitalTrainSuite;

namespace DigitalTrainSuite.UserControls
{

	public partial class UserControlSensorController : UserControl, IMoveableUserControl, IDeleteable
	{

		private delegate void sensorTrippedDelegate(int tagId, int trainId, double speed, bool direction, bool front);

		private APIControl control;

		public APIControl Control
		{
			get { return control; }
			set { control = value; }
		}
	
		private SignalState signalState;

		private UserControlSensorController directionASensor;

		public UserControlSensorController DirectionASensor
		{
			get { return directionASensor; }
			set { directionASensor = value; }
		}

		private UserControlSensorController directionBSensor;

		public UserControlSensorController DirectionBSensor
		{
			get { return directionBSensor; }
			set { directionBSensor = value; }
		}

		private int directionASensorId;

		public int DirectionASensorId
		{
			get { return directionASensorId; }
			set 
			{ 
				directionASensorId = value;
				this.toolStripComboBoxDirectionASensor.Text = value.ToString();
			}
		}

		private int directionBSensorId;

		public int DirectionBSensorId
		{
			get { return directionBSensorId; }
			set 
			{ 
				directionBSensorId = value;
				this.toolStripComboBoxDirectionBSensor.Text = value.ToString();
			}
		}

		private Dictionary<int, UserControlSensorController> sensorControls;

		public Dictionary<int, UserControlSensorController> SensorControls
		{
			get { return sensorControls;}
			set { sensorControls = value;}
		}
	

		private int directionATrainId;

		public int DirectionATrainId
		{
			get { return directionATrainId; }
			set 
			{ 
				directionATrainId = value;
				this.toolStripTextBoxDirectionATrain.Text = value.ToString();
			}
		}

		private int directionBTrainId;

		public int DirectionBTrainId
		{
			get { return directionBTrainId; }
			set 
			{ 
				directionBTrainId = value;
				this.toolStripTextBoxDirectionBTrain.Text = value.ToString();
			}
		}

		private int slowSpeed;

		public int SlowSpeed
		{
			get { return slowSpeed; }
			set 
			{ 
				slowSpeed = value;
				this.toolStripTextBoxSlowSpeed.Text = value.ToString();
			}
		}

		private int goSpeed;

		public int GoSpeed
		{
			get { return goSpeed; }
			set 
			{ 
				goSpeed = value;
				this.toolStripTextBoxGoSpeed.Text = value.ToString();
			}
		}

		private int occupyingTrainId;	

		public int OccupyingTrainId
		{
			get { return occupyingTrainId; }
			set { occupyingTrainId = value; }
		}

		private bool occupied;

		public bool Occupied
		{
			get { return occupied; }
			set { occupied = value; }
		}

		private int sensorId;

		public int SensorId
		{
			get { return sensorId; }
			set
			{ 
				sensorId = value;
				this.userControlSignal1.Id = value;
				this.labelID.Text = value.ToString();
				this.toolStripTextBoxSensorId.Text = value.ToString();
			}
		}
		
		private SensorDriver driver;

		public SensorDriver Driver
		{
			get { return driver; }
			set { 
				driver = value;
				if (driver != null)
				{
					driver.sensorTripped += new SensorTripped(this.driver_sensorTripped);
				}
			}
		}

		void driver_sensorTripped(int sensorId, int tagId, int trainId, double speed, bool direction, bool front)
		{
			if (sensorId == this.sensorId)
			{
				//do something
				this.Invoke(new sensorTrippedDelegate(this.sensorTripped), new object[] { tagId, trainId, speed, direction, front });
			}
			return;
		}

		private bool sensedDirection;

		public bool SensedDirection
		{
			get { return sensedDirection; }
			set 
			{
				if (value != this.sensedDirection)
				{
					switch (this.rotation)
					{
						case RotateFlipType.RotateNoneFlipNone:
							if (value) this.panelRightLeft.BackgroundImage = this.imageListLeftRight.Images["ArrowLeft.bmp"];
							else this.panelRightLeft.BackgroundImage = this.imageListLeftRight.Images["ArrowRight.bmp"];
							break;
						case RotateFlipType.Rotate90FlipNone:
							if (value) this.panelRightLeft.BackgroundImage = this.imageListUpDown.Images["ArrowUp.bmp"];
							else this.panelRightLeft.BackgroundImage = this.imageListUpDown.Images["ArrowDown.bmp"];
							break;
						case RotateFlipType.Rotate180FlipNone:
							if (value) this.panelRightLeft.BackgroundImage = this.imageListLeftRight.Images["ArrowRight.bmp"];
							else this.panelRightLeft.BackgroundImage = this.imageListLeftRight.Images["ArrowLeft.bmp"];
							break;
						case RotateFlipType.Rotate270FlipNone:
							if (value) this.panelRightLeft.BackgroundImage = this.imageListUpDown.Images["ArrowDown.bmp"];
							else this.panelRightLeft.BackgroundImage = this.imageListUpDown.Images["ArrowUp.bmp"];
							break;
						default:
							break;
					}
					sensedDirection = value;
				}
			}
		}


		void sensorTripped(int tagId, int trainId, double speed, bool direction, bool front)
		{
			if (front)
			{
				this.panel4.Visible = true;
				this.SensedDirection = direction;
				this.occupied = true;
				if (trainId != 0) this.OccupyingTrainId = trainId;
				else this.OccupyingTrainId = direction ? this.DirectionATrainId : this.DirectionBTrainId;
				if (this.checkBoxSignalActive.Checked && this.occupyingTrainId != 0)
				{
					try
					{
						if (this.sensorControls != null)
						{
							if (this.DirectionASensor == null)
							{
								this.DirectionASensor = this.sensorControls[this.directionASensorId];
								this.DirectionBSensor = this.sensorControls[this.directionBSensorId];
							}
							this.DirectionASensor.DirectionATrainId = this.occupyingTrainId;
							this.DirectionBSensor.DirectionBTrainId = this.occupyingTrainId;
						}
					}
					catch (KeyNotFoundException e)
					{

					}
					switch (this.signalState)
					{
						case SignalState.RED:
							this.control.controlLocomotive(this.occupyingTrainId, 0, false, false);
							break;
						case SignalState.YELLOW:
							this.control.controlLocomotive(this.occupyingTrainId, this.slowSpeed, false, true);
							break;
						case SignalState.GREEN:
							this.control.controlLocomotive(this.occupyingTrainId, this.goSpeed, false, true);
							break;
						default:
							break;
					}
				}
			}
			else
			{
				this.panel4.Visible = false;
				this.occupied = false;
			}
		}

		void  userControlSignal1_signalStateChanged(int id, SignalState state)
		{
 			this.signalState = state;
			if (this.checkBoxSignalActive.Checked && this.occupied)
			{
				switch (state)
				{
					case SignalState.GREEN:
						this.control.controlLocomotive(this.occupyingTrainId, this.goSpeed, false, false);
						break;
					case SignalState.YELLOW:
						this.control.controlLocomotive(this.occupyingTrainId, this.slowSpeed, false, false);
						break;
					case SignalState.RED:
						break;
					default:
						break;
				}
			}
		}

		public UserControlSensorController()
		{
			InitializeComponent();
			this.DoubleBuffered = true;
			this.SetStyle(ControlStyles.OptimizedDoubleBuffer, true);
			this.SetStyle(ControlStyles.AllPaintingInWmPaint, true);
			this.userControlSignal1.signalStateChanged += new SignalStateChanged(userControlSignal1_signalStateChanged);
			this.ContextMenuStrip = this.contextMenuStripEdit;
			this.redrawArrow();
		}

		public UserControlSensorController(int sensorId, SensorDriver driver, APIControl control)
		{
			InitializeComponent();
			this.DoubleBuffered = true;
			this.SetStyle(ControlStyles.OptimizedDoubleBuffer, true);
			this.SetStyle(ControlStyles.AllPaintingInWmPaint, true);
			this.SensorId = sensorId;
			this.Driver = driver;
			this.driver.sensorTripped += new SensorTripped(this.driver_sensorTripped);
			this.Control = control;
			this.userControlSignal1.signalStateChanged += new SignalStateChanged(userControlSignal1_signalStateChanged);
			this.ContextMenuStrip = this.contextMenuStripEdit;
			this.redrawArrow();
		}

		private void checkBoxSignalActive_CheckedChanged(object sender, EventArgs e)
		{
			if (this.checkBoxSignalActive.Checked) this.userControlSignal1.Enabled = true;
			else this.userControlSignal1.Enabled = false;
		}

		private void toolStripTextBoxSensorId_KeyDown(object sender, KeyEventArgs e)
		{
			if (e.KeyCode == Keys.Enter)
			{
				try
				{
					this.SensorId = Convert.ToInt32(this.toolStripTextBoxSensorId.Text);
					this.contextMenuStripEdit.Close();
				}
				catch
				{
					this.toolStripTextBoxSensorId.Text = "";
				}
			}
		}

		private void toolStripTextBoxSensorId_TextChanged(object sender, EventArgs e)
		{
			try
			{
				this.SensorId = Convert.ToInt32(this.toolStripTextBoxSensorId.Text);
			}
			catch
			{
				this.toolStripTextBoxSensorId.Text = "";
			}
		}

		private void toolStripTextBoxSlowSpeed_TextChanged(object sender, EventArgs e)
		{
			try
			{
				this.SlowSpeed = Convert.ToInt32(this.toolStripTextBoxSlowSpeed.Text);
			}
			catch
			{
				this.toolStripTextBoxSlowSpeed.Text = "";
			}
		}

		private void toolStripTextBoxGoSpeed_TextChanged(object sender, EventArgs e)
		{
			try
			{
				this.GoSpeed = Convert.ToInt32(this.toolStripTextBoxGoSpeed.Text);
			}
			catch
			{
				this.toolStripTextBoxGoSpeed.Text = "";
			}
		}

		private void toolStripTextBoxSlowSpeed_KeyDown(object sender, KeyEventArgs e)
		{
			if (e.KeyCode == Keys.Enter)
			{
				try
				{
					this.SlowSpeed = Convert.ToInt32(this.toolStripTextBoxSlowSpeed.Text);
					this.contextMenuStripEdit.Close();
				}
				catch
				{
					this.toolStripTextBoxSlowSpeed.Text = "";
				}
			}
		}

		private void toolStripTextBoxGoSpeed_KeyDown(object sender, KeyEventArgs e)
		{
			if (e.KeyCode == Keys.Enter)
			{
				try
				{
					this.GoSpeed = Convert.ToInt32(this.toolStripTextBoxGoSpeed.Text);
					this.contextMenuStripEdit.Close();
				}
				catch
				{
					this.toolStripTextBoxGoSpeed.Text = "";
				}
			}
		}

		private void toolStripTextBoxDirectionATrain_TextChanged(object sender, EventArgs e)
		{
			try
			{
				this.DirectionATrainId = Convert.ToInt32(this.toolStripTextBoxDirectionATrain.Text);
			}
			catch
			{
				this.toolStripTextBoxDirectionATrain.Text = "";
			}
		}

		private void toolStripTextBoxDirectionBTrain_TextChanged(object sender, EventArgs e)
		{
			try
			{
				this.DirectionBTrainId = Convert.ToInt32(this.toolStripTextBoxDirectionBTrain.Text);
			}
			catch
			{
				this.toolStripTextBoxDirectionBTrain.Text = "";
			}
		}

		#region IMoveableUserControl Members

		private bool moving = false;

		private Point origin;

		private bool movable = true;

		public bool Movable
		{
			get
			{
				return this.movable;
			}
			set
			{
				this.movable = value;
			}
		}

		private RotateFlipType rotation = RotateFlipType.RotateNoneFlipNone;

		public RotateFlipType Rotation
		{
			get
			{
				return this.rotation;
			}
			set
			{
				this.rotation = value;
				this.redrawArrow();
			}
		}

		private void redrawArrow()
		{
			if (this.Movable)
			{
				switch (this.rotation)
				{
					case RotateFlipType.RotateNoneFlipNone:
						this.panelRightLeft.BackgroundImage = this.imageListLeftRight.Images["ArrowLeft.bmp"];
						this.panelRightLeft.Visible = true;
						this.panelUpDown.Visible = false;
						break;
					case RotateFlipType.Rotate90FlipNone:
						this.panelUpDown.BackgroundImage = this.imageListUpDown.Images["ArrowUp.bmp"];
						this.panelRightLeft.Visible = false;
						this.panelUpDown.Visible = true;
						break;
					case RotateFlipType.Rotate180FlipNone:
						this.panelRightLeft.BackgroundImage = this.imageListLeftRight.Images["ArrowRight.bmp"];
						this.panelRightLeft.Visible = true;
						this.panelUpDown.Visible = false;
						break;
					case RotateFlipType.Rotate270FlipNone:
						this.panelUpDown.BackgroundImage = this.imageListUpDown.Images["ArrowDown.bmp"];
						this.panelRightLeft.Visible = false;
						this.panelUpDown.Visible = true;
						break;
					default:
						break;
				}
			}
		}

		#endregion

		private void noRotationToolStripMenuItem_Click(object sender, EventArgs e)
		{
			this.Rotation = RotateFlipType.RotateNoneFlipNone;
		}

		private void rotate90ToolStripMenuItem_Click(object sender, EventArgs e)
		{
			this.Rotation = RotateFlipType.Rotate90FlipNone;
		}

		private void rotate180ToolStripMenuItem_Click(object sender, EventArgs e)
		{
			this.Rotation = RotateFlipType.Rotate180FlipNone;
		}

		private void rotate270ToolStripMenuItem_Click(object sender, EventArgs e)
		{
			this.Rotation = RotateFlipType.Rotate270FlipNone;
		}

		#region IDeleteable Members

		public event DeleteControl deleteControl;

		public void deleteThis()
		{
			if (this.deleteControl != null)
			{
				this.deleteControl(this);
			}
		}

		#endregion

		private void UserControlSensorController_MouseMove(object sender, MouseEventArgs e)
		{
			if (this.moving)
			{
				this.Location = new Point(this.Location.X + e.X - this.origin.X, this.Location.Y + e.Y - this.origin.Y);
			}
		}

		private void UserControlSensorController_MouseDown(object sender, MouseEventArgs e)
		{
			if (this.movable)
			{
				this.origin = new Point(e.X, e.Y);
				this.moving = true;
			}
		}

		private void UserControlSensorController_MouseUp(object sender, MouseEventArgs e)
		{
			this.moving = false;
		}

		private void toolStripComboBoxDirectionASensor_TextChanged(object sender, EventArgs e)
		{
			try
			{
				this.directionASensorId = Convert.ToInt32(this.toolStripComboBoxDirectionASensor.Text);
			}
			catch
			{
				this.toolStripComboBoxDirectionASensor.Text = "";
			}
		}

		private void toolStripComboBoxDirectionBSensor_TextChanged(object sender, EventArgs e)
		{
			try
			{
				this.directionBSensorId = Convert.ToInt32(this.toolStripComboBoxDirectionBSensor.Text);
			}
			catch
			{
				this.toolStripComboBoxDirectionBSensor.Text = "";
			}
		}
	}
}
